package asteroids.factory;

import java.awt.Color;

import org.apache.log4j.Logger;

import asteroids.engine.Utils;
import asteroids.entity.PlayerShip;
import asteroids.entity.Ship;
import asteroids.entity.ShipIcing;
import asteroids.entity.equipment.Dynamo;
import asteroids.entity.equipment.ForceShield;
import asteroids.entity.equipment.LaunchFighters;
import asteroids.entity.equipment.MADDevice;
import asteroids.entity.equipment.PointDefense;
import asteroids.entity.equipment.ShivaFurnace;
import asteroids.entity.weapon.ClassicWeapon;
import asteroids.entity.weapon.ConfigurableWeapon;
import asteroids.entity.weapon.CruiseMissiles;
import asteroids.entity.weapon.PhotonCrystals;

public class Shipyard
{
    private static final Logger logger = Logger.getLogger(Shipyard.class);

    /**
     * returns a ship with the default classic asteroids shape
     * 
     * @return
     */
    public static Ship getClassicShip(String name, double x, double y)
    {
        Ship s = new PlayerShip(name, x, y, ShapeLib.WEDGE_SHAPE);
        s.arm(new ClassicWeapon(s));
        return s;
    }

    /**
     * returns a ship with the specified shape
     * 
     * @return
     */
    public static Ship getClassicShip(String name, double x, double y, Utils.PolarCoordinate[] shape)
    {
        Ship s = new PlayerShip(name, x, y, shape);
        s.arm(new ClassicWeapon(s));
        return s;
    }

    /**
     * returns a ship from the ShapeLib, after configuring its hardpoints
     * 
     * @return
     */
    @Deprecated
    // this will no longer function correctly
    public static Ship getClassicShip(String name, double x, double y, ShapeLib.ShipType type)
    {
        PlayerShip s = new PlayerShip(name, x, y, ShapeLib.shipShapes[type.ordinal()]);
        s.setHardPoints(ShapeLib.shipPoints[type.ordinal()]);
        s.arm(new ClassicWeapon(s));
        return s;
    }

    public static Ship buildShip(String name, double x, double y, ShapeLib.ShipType type)
    {
        double scaleFactor = 0.6;
        ShipConfig sc = ShapeLib.shipConfigs[type.ordinal()];
        PlayerShip ship = new PlayerShip(name, x, y, Utils.scalePolarShape(sc.shape, scaleFactor),
                sc.turnSpeed, sc.acceleration, sc.maxEnergy, sc.integrity, sc.mass);
        ship.setHardPoints(sc.hardPoints);
        for( Utils.PolarCoordinate[] b : sc.bling )
        {
            ShipIcing si = new ShipIcing(x, y, ship, Utils.scalePolarShape(b, scaleFactor));
            // set color? need to add that to the ShipConfig if so
            ship.addBling(si);
        }
        ship.equip(new ShivaFurnace(ship, sc.energyRegen, sc.regenDelay));
        outfit(ship, type);
        // Stockpile.arm(pShip, sc.weaponType);
        // Stockpile.equip(pShip, sc.equipmentType);

        return ship;
    }

    @Deprecated
    public static Ship buildBroodhome(String name, double x, double y)
    {
        double scaleFactor = 0.6;
        Utils.PolarCoordinate[] bShape = Utils.scalePolarShape(ShapeLib.BROODHOME_SHAPE,
                scaleFactor);
        // printShape(cShape);
        PlayerShip b = new PlayerShip(name, x, y, bShape, 76.68 / Utils.FRAMES_PER_SECOND, 32.4
                / Utils.FRAMES_PER_SECOND / Utils.FRAMES_PER_SECOND, 30, 36.0, 10);
        b.setColor(Color.GRAY);
        for( Utils.PolarCoordinate[] pc : ShapeLib.BROODHOME_BLING )
        {
            ShipIcing si = new ShipIcing(x, y, b, Utils.scalePolarShape(pc, scaleFactor));
            si.setColor(Color.LIGHT_GRAY);
            b.addBling(si);
        }
        b.arm(new PhotonCrystals(b));
        b.equip(new Dynamo(b, 6.0 / Utils.FRAMES_PER_SECOND));
        return b;
    }

    @Deprecated
    public static Ship buildCruiser(String name, double x, double y)
    {
        double scaleFactor = 0.6;
        Utils.PolarCoordinate[] cShape = Utils.scalePolarShape(ShapeLib.CRUISER_SHAPE, scaleFactor);
        PlayerShip c = new PlayerShip(name, x, y, cShape, 337.5 / Utils.FRAMES_PER_SECOND, 28.8
                / Utils.FRAMES_PER_SECOND / Utils.FRAMES_PER_SECOND, 18, 18, 6);
        for( Utils.PolarCoordinate[] pc : ShapeLib.CRUISER_BLING )
        {
            c.addBling(new ShipIcing(x, y, c, Utils.scalePolarShape(pc, scaleFactor)));
        }
        c.arm(new CruiseMissiles(c));
        c.equip(new Dynamo(c, (0.111 * 24) / Utils.FRAMES_PER_SECOND));
        c.setSpecial(new PointDefense(c));
        return c;
    }

    @Deprecated
    public static Ship buildDreadnaught(String name, double x, double y)
    {
        double scaleFactor = 0.6;
        Utils.PolarCoordinate[] dShape = Utils.scalePolarShape(ShapeLib.DREADNAUGHT_SHAPE,
                scaleFactor);
        PlayerShip d = new PlayerShip(name, x, y, dShape, (22.5 * 0.2) * 24
                / Utils.FRAMES_PER_SECOND, (((30 / 4) * .2) * 24) / Utils.FRAMES_PER_SECOND
                / Utils.FRAMES_PER_SECOND, 42, 42, 10);
        for( Utils.PolarCoordinate[] pc : ShapeLib.DREADNAUGHT_BLING )
        {
            d.addBling(new ShipIcing(x, y, d, Utils.scalePolarShape(pc, scaleFactor)));
        }
        d.arm(new ConfigurableWeapon(d, 150d / Utils.FRAMES_PER_SECOND, 6, 6,
                Utils.FRAMES_PER_SECOND, (int) ((9d * Utils.FRAMES_PER_SECOND) / 24d), false));
        d.equip(new Dynamo(d, (0.14 * 24) / Utils.FRAMES_PER_SECOND));
        d.setSpecial(new LaunchFighters(d));
        return d;
    }

    @Deprecated
    public static Ship buildTerminator(String name, double x, double y)
    {
        double scaleFactor = 0.6;
        Utils.PolarCoordinate[] tShape = Utils.scalePolarShape(ShapeLib.TERMINATOR_SHAPE,
                scaleFactor);
        PlayerShip t = new PlayerShip(name, x, y, tShape, 222.75 / Utils.FRAMES_PER_SECOND, 45.0
                / Utils.FRAMES_PER_SECOND / Utils.FRAMES_PER_SECOND, 10, 20, 3);
        for( Utils.PolarCoordinate[] pc : ShapeLib.TERMINATOR_BLING )
        {
            t.addBling(new ShipIcing(x, y, t, Utils.scalePolarShape(pc, scaleFactor)));
        }
        t.setHardPoints(ShapeLib.TERMINATOR_HARDPOINTS);
        t.equip(new Dynamo(t, 6.96 / Utils.FRAMES_PER_SECOND));
        t.arm(new ConfigurableWeapon(t, 240d / Utils.FRAMES_PER_SECOND, 1, 2,
                Utils.FRAMES_PER_SECOND / 2, 0, false));
        t.setSpecial(new ForceShield(t));
        return t;
    }

    public static void printShape(Utils.PolarCoordinate[] s)
    {
        System.out.println("{");
        for( int i = 0; i < s.length - 1; i++ )
        {
            Utils.PolarCoordinate p = s[i];
            System.out.println("Utils.createPolarCoordinate(" + p.getRotation() + ", "
                    + p.getRadius() + "),");
        }

        Utils.PolarCoordinate p = s[s.length - 1];
        System.out.println("Utils.createPolarCoordinate(" + p.getRotation() + ", " + p.getRadius()
                + ")");

        System.out.println("}");
    }

    public static void outfit(Ship ship, ShapeLib.ShipType type)
    {
        switch (type)
        {
            case CLASSIC:
                ship.arm(new ClassicWeapon(ship));
                break;
            case BROODHOME:
                ship.arm(new PhotonCrystals(ship));
                // ship.equip(new Dynamo(ship, 6.0 / Utils.FRAMES_PER_SECOND));
                break;
            case CRUISER:
                ship.arm(new CruiseMissiles(ship));
                // ship.equip(new Dynamo(ship, (0.111 * 24) /
                // Utils.FRAMES_PER_SECOND));
                ship.setSpecial(new PointDefense(ship));
                break;
            case DREADNAUGHT:
                Utils.PolarCoordinate[] fusionBoltShape = {
                        Utils.polarFromCartesian(Utils.createCartesianCoordinate(8.5, 0.0)),
                        Utils.polarFromCartesian(Utils.createCartesianCoordinate(6.5, -2.0)),
                        Utils.polarFromCartesian(Utils.createCartesianCoordinate(0.5, -2.0)),
                        Utils.polarFromCartesian(Utils.createCartesianCoordinate(-5.5, -0.0)),
                        Utils.polarFromCartesian(Utils.createCartesianCoordinate(-8.5, 0.0)),
                        Utils.polarFromCartesian(Utils.createCartesianCoordinate(-5.5, 0.0)),
                        Utils.polarFromCartesian(Utils.createCartesianCoordinate(0.5, 2.0)),
                        Utils.polarFromCartesian(Utils.createCartesianCoordinate(6.5, 2.0)) };
                ship.arm(new ConfigurableWeapon(ship, 250d / Utils.FRAMES_PER_SECOND, 6, 6,
                        (int) (0.8 * Utils.FRAMES_PER_SECOND),
                        (int) ((9d * Utils.FRAMES_PER_SECOND) / 24d), false, Utils.scalePolarShape(
                                fusionBoltShape, 0.6)));
                ship.setSpecial(new LaunchFighters(ship));
                ship.equip(new MADDevice(ship, ShapeLib.shipLength * 3));
                break;
            case TERMINATOR:
                ship.arm(new ConfigurableWeapon(ship, 240d / Utils.FRAMES_PER_SECOND, 1, 1,
                        Utils.FRAMES_PER_SECOND / 2, (int) Math
                                .round(((1d * Utils.FRAMES_PER_SECOND) / 24)), false));
                ship.setSpecial(new ForceShield(ship));
                break;
            default:
                logger.warn("Outfitting an unknown shipType");
                ship.arm(new ClassicWeapon(ship));
        }
    }
}

// acceleration from max speed
// (((worldunitsperframe / 4) * .2) * 24) / Utils.FRAMES_PER_SECOND /
// Utils.FRAMES_PER_SECOND
// turnspeed from facings/frame
// (22.5 * facingsperframe) * 24 / Utils.FRAMES_PER_SECOND
